#pragma once

#include "fxcc/mono/pch.h"
#include "fxcc/mono/Method.h"
#include "fxcc/mono/Object.h"
#include "fxcc/mono/Field.h"

namespace mono
{
    struct FXCC_API Clazz
    {
     
        struct FXCC_API Desc
        {
            std::string m_Namespace;

            std::string m_Name;

            MonoImage *image;

            bool operator<(const Clazz::Desc &other) const
            {
                return std::tie(m_Namespace, m_Name) < std::tie(other.m_Namespace, other.m_Name);
            };

        } m_Desc;

        MonoClass *klass;

        bool m_IsEnum;

        bool m_Available;

        std::vector<std::shared_ptr<mono::Field>> m_Fields, m_EnumValues;

        std::map<mono::Method::Desc, std::shared_ptr<mono::Method>> m_Methods;

        Clazz(const Desc &desc)
            : m_Desc(desc), m_IsEnum(false)
        {
            m_Available = Init();
        }

        std::shared_ptr<Object> NewObject();

        bool Init();

        bool RuntimeInit();

        bool GetAllMethods();

        bool LoadMethod(const Method::Desc& desc);

        bool LoadMethod(const std::string& name,const int& numParam);
        
        std::shared_ptr<Method> GetMethod(const std::string &name, int numParam);

        bool HasMethod(const Method::Desc& desc);

        std::shared_ptr<Method> GetMethod(const Method::Desc& desc)
        {
            auto it = m_Methods.find(desc);
            if (it != m_Methods.end())
            {
                return it->second;
            }
            return 0;
        }
    };
};